/**
Filename: miniwrite.c
Alumno: Jianpei Ye
Práctica: practica4b
Asignatura: Lab. SS.OO
**/
/*
Ejemplo: miniwrite enviar jianpei
	 miniwrite recibir root
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <utmp.h>
#include <unistd.h>

#define MAX 512
#define CR 10

/* Prototipo de funciones */
char *leer_cadena();
void fin_comunicacion(int sig);

/* Variables globales */
int tuberia12, tuberia21;
char nombre_tuberia12[MAX], nombre_tuberia21[MAX];
char mensaje[MAX];
int estado;


/* Función main */
int main(int argc, char* argv[])
{
    char terminal[MAX];
    char *cadena;
    char *logname;

    struct utmp *utmp;

    int tty;
    enum {ENVIAR, RECIBIR} operacion;
    enum {TECLADO, TUBERIA} origen;


    if (argc != 3 || ((strcmp(argv[1],"recibir")) != 0 && (strcmp(argv[1], "enviar")) != 0))
    {
        perror("Error en los parámetros de entrada.\nENVIAR MENSAJE: miniwrite enviar [username]\nRECIBIR MENSAJE: miniwrite recibir [username]\n");
        exit(-1);
    }
    else if((strcmp(argv[1],"enviar")) == 0)
        operacion = ENVIAR;
    else
        operacion = RECIBIR;

    logname = getenv("LOGNAME");

    if((strcmp(logname,argv[2])) == 0)
    {
        perror("No se permite la comunicación con uno mismo.\n");
        exit(0);
    }

    while ((utmp = getutent()) != NULL)
    {
        if (!strcmp(utmp->ut_user, argv[2]))
        {
            sprintf(terminal, "/dev/%s", utmp->ut_line);
            break;
        }
    }

    if (utmp == NULL)
    {
        printf("El usuario %s no está conectado \n", argv[1]);
        exit(0);
    }
/*
    sprintf(nombre_tuberia12,"/tmp/%s_to_%s",logname,argv[2]);
    sprintf(nombre_tuberia21,"/tmp/%s_to_%s",argv[2],logname);
*/
    if(operacion == ENVIAR)
    {
	sprintf(nombre_tuberia12,"/tmp/%s","tuberia12");
	sprintf(nombre_tuberia21,"/tmp/%s","tuberia21");
    }
    else if (operacion == RECIBIR)
    {
    	sprintf(nombre_tuberia12,"/tmp/%s","tuberia21");
	sprintf(nombre_tuberia21,"/tmp/%s","tuberia12");
    }
    
    
    
    if(operacion == ENVIAR)
    {
        unlink(nombre_tuberia12);
        unlink(nombre_tuberia21);

        umask(~0666);

        if(mkfifo(nombre_tuberia12,0666) == -1)
        {
            perror(nombre_tuberia12);
            exit(-1);
        }
        if(mkfifo(nombre_tuberia21,0666) == -1)
        {
            perror(nombre_tuberia21);
            exit(-1);
        }
        
        /* Abrir el terminal del usuario */
        sprintf(terminal, "/dev/%s", utmp->ut_line);
        if ((tty = open(terminal, O_RDWR)) == -1)
        {
            perror("Error abriendo el terminal");
            exit(-1);
        }


        /* Avisar al usuario */
        sprintf(mensaje, "\n EL USUARIO %s QUIERE ENVIARTE UN MENSAJE\07\nPARA ACEPTAR, EJECUTAR EL PROGRAMA 'miniwrite recibir %s\n\n",logname,logname);
        write(tty,mensaje,strlen(mensaje) + 1);
        close(tty);

        printf("Esperando respuesta ... \n");
    }


    /*----------------------------------------------------------------*/
    if((tuberia21 = open(nombre_tuberia21,O_RDONLY | O_NDELAY)) == -1 || (tuberia12 = open(nombre_tuberia12,O_WRONLY)) == -1)
    {
        if(tuberia12 == -1)
            perror(nombre_tuberia12);
        else
            perror(nombre_tuberia21);

        exit(-1);
    }

    if(operacion == ENVIAR)
        printf("El usuario ha aceptado la comunicación.\07\n");

    estado = fcntl(0,F_GETFL,0);
    if(fcntl(0,F_SETFL,estado | O_NDELAY) == -1)
        perror("fcntl");

    signal(SIGINT,fin_comunicacion);

    printf("%s: ",logname);
    fflush(stdout);

    do
    {
        if((cadena = leer_cadena()) != NULL)
        {
            if(cadena[0] != 0)
            {
                strcpy(mensaje,cadena);
                write(tuberia12,mensaje,strlen(cadena) + 1);
            }
            printf("%s: ",logname);
            fflush(stdout);

            origen = TECLADO;
        }
        if(read(tuberia21,mensaje, MAX) > 0)
        {
            printf("\n%s: %s\n", argv[2],mensaje);
            printf("%s: ",logname);
            fflush(stdout);
            origen = TUBERIA;
        }

        sleep(1);
    }
    while((strcmp(mensaje,"terminar")) != 0);

    fcntl(0,F_SETFL, estado);

    if(origen == TECLADO)
    {
        sprintf(mensaje,"terminar");
        write(tuberia12,mensaje,strlen(mensaje) + 1);
    }

    printf("\nFin de Comunicación\n");
    close(tuberia12);
    close(tuberia21);
    exit(0);

    return 0;
}

char *leer_cadena()
{
    static char cadena_leida[MAX];
    static int flag_primera_vez = 1;
    char cadena[MAX];
    int numero_bytes;
    int i;

    if (flag_primera_vez)
    {
        cadena_leida[0] = '\0';
        flag_primera_vez--;
    }

    numero_bytes = read(0,cadena,MAX);
    if(numero_bytes == 0)
    {
        return(NULL);
    }

    for(i = 0; i < numero_bytes; i++)
    {
        if(cadena[i] == CR)
        {
            cadena[i] = '\0';
            strcat(cadena_leida,cadena);
            flag_primera_vez++;
            return(cadena_leida);
        }
    }

    cadena[i] = '\0';
    strcat(cadena_leida,cadena);
    return(NULL);

}

void fin_comunicacion(int sig)
{
    fcntl(0,F_SETFL,estado);
    sprintf(mensaje,"terminar");
    write(tuberia12,mensaje,strlen(mensaje) + 1);
    printf("\nFin de Comunicación.\n");
    close(tuberia12);
    close(tuberia21);
    exit(0);
}
